﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna;
using KinectTD.MapControl;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Media;
using KinectTD.UI;
using KinectTD.Towers;
using KinectTD.Input;
using KinectTD.Agents;
using Microsoft.Xna.Framework.Audio;
namespace KinectTD.Game_Management
{
	class Level
	{

		private static int wave = 1;

		private Map map;
		private Player player;


		private Texture2D ribbon;
		private Texture2D scoreBar;
		private Texture2D radiusTexture;
		private Texture2D turretTexture;
		private Texture2D placeUpgradeTexture;

		private Texture2D moneyTexture;
		private Texture2D healthTexture;


		private Rectangle mapRect;
		private Rectangle toolRect;
		private Rectangle scoreRect;
		private List<Button> uiPlaceButtons;
		private List<Button> uiUpgradeButtons;
		private List<Texture2D> turretAmmoTextures;


		private SpriteFont scoreFont;

		private Dictionary<string, Texture2D> towerTextures;
		private Dictionary<string, Texture2D> ammoTextures;

		private Dictionary<string, Texture2D> enemyTextures;

		private List<Enemy> levelEnemies = new List<Enemy>();
		private static Random r = new Random();

		private bool placing = false;
		private bool canPlace = true;
		private Tower towerToPlace;
		private Color radiusColour = Color.White;

		private bool placingUpgrade = false;
		private UPGRADE_TYPE typeUpgrade = UPGRADE_TYPE.DAMAGE;
		private int upgradeCost = 0;

		private ControlledTurret turret;

		private SpriteFont dialogTextFont;
		private string dialog;
		private Vector2 dialogPos = new Vector2(0, -500);
		private enum levelStates { PLACE_MODE, PLAYING }

		private levelStates STATE = levelStates.PLACE_MODE;

		private Button closeButton;

		private SoundEffect deathSound;

		public Level(Player levelPlayer, Viewport activeViewport)
		{

			player = levelPlayer;

			uiPlaceButtons = new List<Button>();
			uiUpgradeButtons = new List<Button>();
			towerTextures = new Dictionary<string, Texture2D>();
			ammoTextures = new Dictionary<string, Texture2D>();

			scoreRect = mapRect = toolRect = activeViewport.Bounds;

			toolRect.Height = (int)(activeViewport.Height * 0.15);

			mapRect.Y = toolRect.Height;
			mapRect.Height = (int)(activeViewport.Height * 0.80);

			scoreRect.Y = mapRect.Height + toolRect.Height;
			scoreRect.Height = (int)(activeViewport.Height * 0.05);

			turretAmmoTextures = new List<Texture2D>();
			enemyTextures = new Dictionary<string, Texture2D>();
			dialog = "wut?";
		}


		//Sets up the UI to control the towers we can buy
		private void InitButtons()
		{
			closeButton = new Button("Buttons/cake");
			closeButton.Position = new Vector2(10, 20);
			closeButton.Size = new Vector2(100, 110);
			closeButton.Clicked += new Button.ClickedEventHandler(closeButton_Clicked);


			FireTower ft = new FireTower(Vector2.Zero, towerTextures["fire"], radiusTexture, levelEnemies, ammoTextures["fire"]);
			ft.IsButton = true;
			TowerButton fireTower = new TowerButton("Buttons/GameButton", ft);
			fireTower.Position = new Vector2(140, 10);
			fireTower.Tower.Position = new Vector2(fireTower.Position.X + (fireTower.Size.X / 5), fireTower.Position.Y + (fireTower.Size.Y / 5));
			fireTower.Size = new Vector2(150, 150);
			fireTower.Clicked += new KinectTD.UI.Button.ClickedEventHandler(fireTowerButton_Clicked);
			uiPlaceButtons.Add(fireTower);

			WaterTower wt = new WaterTower(Vector2.Zero, towerTextures["water"], radiusTexture, levelEnemies, ammoTextures["water"]);
			wt.IsButton = true;
			TowerButton waterTower = new TowerButton("Buttons/GameButton", wt);
			waterTower.Position = new Vector2(480, 10);
			waterTower.Tower.Position = new Vector2(waterTower.Position.X + (waterTower.Size.X / 5), waterTower.Position.Y + (waterTower.Size.Y / 5));
			waterTower.Size = new Vector2(150, 150);
			waterTower.Clicked += new KinectTD.UI.Button.ClickedEventHandler(waterTowerButton_Clicked);
			uiPlaceButtons.Add(waterTower);

			PoisonTower pt = new PoisonTower(Vector2.Zero, towerTextures["poison"], radiusTexture, levelEnemies, ammoTextures["poison"]);
			pt.IsButton = true;
			TowerButton poisonTower = new TowerButton("Buttons/GameButton", pt);
			poisonTower.Position = new Vector2(310, 10);
			poisonTower.Tower.Position = new Vector2(poisonTower.Position.X + (poisonTower.Size.X / 5), poisonTower.Position.Y + (poisonTower.Size.Y / 5));
			poisonTower.Size = new Vector2(150, 150);
			poisonTower.Clicked += new KinectTD.UI.Button.ClickedEventHandler(poisonTowerButton_Clicked);
			uiPlaceButtons.Add(poisonTower);




			SuperTower st = new SuperTower(Vector2.Zero, towerTextures["super"], radiusTexture, levelEnemies, ammoTextures["super"]);
			st.IsButton = true;
			TowerButton superTower = new TowerButton("Buttons/GameButton", st);
			superTower.Position = new Vector2(650, 10);
			superTower.Tower.Position = new Vector2(superTower.Position.X + (superTower.Size.X / 5), superTower.Position.Y + (superTower.Size.Y / 5));
			superTower.Size = new Vector2(150, 150);
			superTower.Clicked += new KinectTD.UI.Button.ClickedEventHandler(superTowerButton_Clicked);
			uiPlaceButtons.Add(superTower);


			Button startButton = new Button("Buttons/Start");
			startButton.Position = new Vector2(Engine.GameViewport.Width - 457, 10);
			startButton.Clicked += new Button.ClickedEventHandler(startButton_Clicked);
			startButton.Size = new Vector2(350, 130);

			uiPlaceButtons.Add(startButton);


			UpgradeButton damageUpgrade = new UpgradeButton("Buttons/GameButton", "Towers/Upgrades/Damage");
			damageUpgrade.Position = new Vector2(140, 10);
			damageUpgrade.Cost = 300;
			damageUpgrade.Size = new Vector2(150, 150);
			damageUpgrade.IconPosition = new Vector2(damageUpgrade.Position.X + (damageUpgrade.Size.X / 4), damageUpgrade.Position.Y);
			damageUpgrade.IconSize = damageUpgrade.Size / new Vector2(2);

			damageUpgrade.Clicked += new Button.ClickedEventHandler(damageUpgrade_Clicked);

			uiUpgradeButtons.Add(damageUpgrade);

			UpgradeButton rangeUprade = new UpgradeButton("Buttons/GameButton", "Towers/Upgrades/Range");
			rangeUprade.Position = new Vector2(310, 10);
			rangeUprade.Cost = 250;
			rangeUprade.Size = new Vector2(150, 150);
			rangeUprade.IconPosition = new Vector2(rangeUprade.Position.X + (rangeUprade.Size.X / 4), rangeUprade.Position.Y);
			rangeUprade.IconSize = rangeUprade.Size / new Vector2(2);

			rangeUprade.Clicked += new Button.ClickedEventHandler(rangeUpgrade_Clicked);

			uiUpgradeButtons.Add(rangeUprade);

			UpgradeButton rateUpgrade = new UpgradeButton("Buttons/GameButton", "Towers/Upgrades/Rate");
			rateUpgrade.Position = new Vector2(480, 10);
			rateUpgrade.Cost = 120;
			rateUpgrade.Size = new Vector2(150, 150);
			rateUpgrade.IconPosition = new Vector2(rateUpgrade.Position.X + (rateUpgrade.Size.X / 4), rateUpgrade.Position.Y);
			rateUpgrade.IconSize = rateUpgrade.Size / new Vector2(2);

			rateUpgrade.Clicked += new Button.ClickedEventHandler(rateUpgrade_Clicked);

			uiUpgradeButtons.Add(rateUpgrade);

			Button speedButton = new Button("Buttons/Speed");
			speedButton.Position = new Vector2(Engine.GameViewport.Width - 457, 10);
			speedButton.Clicked += new Button.ClickedEventHandler(speedButton_Clicked);
			speedButton.Size = new Vector2(350, 130);

			uiUpgradeButtons.Add(speedButton);

		}

		void closeButton_Clicked(object sender, EventArgs a)
		{
			Engine.GameStack.Push(Engine.MainMenu, true);
		}



		void damageUpgrade_Clicked(object sender, EventArgs a)
		{
			placingUpgrade = true;
			typeUpgrade = UPGRADE_TYPE.DAMAGE;
			placeUpgradeTexture = (sender as UpgradeButton).IconTexture;
			upgradeCost = (sender as UpgradeButton).Cost;
		}

		void rangeUpgrade_Clicked(object sender, EventArgs a)
		{
			placingUpgrade = true;
			typeUpgrade = UPGRADE_TYPE.RANGE;
			placeUpgradeTexture = (sender as UpgradeButton).IconTexture;
			upgradeCost = (sender as UpgradeButton).Cost;


		}
		void rateUpgrade_Clicked(object sender, EventArgs a)
		{
			placingUpgrade = true;
			typeUpgrade = UPGRADE_TYPE.SPEED;
			placeUpgradeTexture = (sender as UpgradeButton).IconTexture;
			upgradeCost = (sender as UpgradeButton).Cost;


		}

		void speedButton_Clicked(object sender, EventArgs a)
		{
			Engine.GAME_SPEED *= 2;
		}


		void startButton_Clicked(object sender, EventArgs a)
		{
			STATE = levelStates.PLAYING;
			placing = false;
			foreach (Tower t in map.placedTowers)
			{
				t.Active = true;
			}

		}

		void waterTowerButton_Clicked(object sender, EventArgs a)
		{
			if (STATE == levelStates.PLACE_MODE)
			{

				towerToPlace = new WaterTower(Vector2.Zero, towerTextures["water"], radiusTexture, levelEnemies, ammoTextures["water"]);
				towerToPlace.Size = (sender as TowerButton).Tower.Size;
				towerToPlace.Size *= new Vector2(2);
				placing = true;


			}
		}

		void poisonTowerButton_Clicked(object sender, EventArgs a)
		{
			if (STATE == levelStates.PLACE_MODE)
			{

				towerToPlace = new PoisonTower(Vector2.Zero, towerTextures["poison"], radiusTexture, levelEnemies, ammoTextures["poison"]);
				towerToPlace.Size = (sender as TowerButton).Tower.Size;
				towerToPlace.Size *= new Vector2(2);
				placing = true;


			}
		}

		void fireTowerButton_Clicked(object sender, EventArgs a)
		{
			if (STATE == levelStates.PLACE_MODE)
			{

				towerToPlace = new FireTower(Vector2.Zero, towerTextures["fire"], radiusTexture, levelEnemies, ammoTextures["fire"]);
				towerToPlace.Size = (sender as TowerButton).Tower.Size;
				towerToPlace.Size *= new Vector2(2);
				placing = true;


			}
		}


		void superTowerButton_Clicked(object sender, EventArgs a)
		{
			if (STATE == levelStates.PLACE_MODE)
			{

				towerToPlace = new SuperTower(Vector2.Zero, towerTextures["super"], radiusTexture, levelEnemies, ammoTextures["super"]);
				towerToPlace.Size = (sender as TowerButton).Tower.Size;
				towerToPlace.Size *= new Vector2(2);
				placing = true;


			}
		}

		public void LoadContent(ContentManager Content)
		{
			//Temporary
			ribbon = Content.Load<Texture2D>("Level/Toolbar");
			scoreBar = ribbon;


            ///All of these AMAZING art resources were provided by http://lostgarden.com
			ammoTextures["water"] = Content.Load<Texture2D>("Towers/Ammo/waterBullet");
			ammoTextures["poison"] = Content.Load<Texture2D>("Towers/Ammo/poisonBullet");
			ammoTextures["fire"] = Content.Load<Texture2D>("Towers/Ammo/fireBullet");
			ammoTextures["super"] = Content.Load<Texture2D>("Towers/Ammo/superBullet");

			towerTextures["water"] = Content.Load<Texture2D>("Towers/waterTower");
			towerTextures["poison"] = Content.Load<Texture2D>("Towers/poisonTower");
			towerTextures["fire"] = Content.Load<Texture2D>("Towers/fireTower");
			towerTextures["super"] = Content.Load<Texture2D>("Towers/superTower");

			enemyTextures.Add("flour", Content.Load<Texture2D>("Enemies/flour"));
			enemyTextures.Add("fruit", Content.Load<Texture2D>("Enemies/currant"));

			Engine.RangeTexture = Content.Load<Texture2D>("Buttons/Range");
			Engine.DamageTexture = Content.Load<Texture2D>("Buttons/Damage");
			Engine.SpeedTexture = Content.Load<Texture2D>("Buttons/Rate");

			dialogTextFont = Content.Load<SpriteFont>("Level/waveFont");
			
			InitButtons();
			closeButton.LoadContent(Content);
			foreach (Button t in uiPlaceButtons)
			{
				t.LoadContent(Content);
			}
			foreach (Button t in uiUpgradeButtons)
				t.LoadContent(Content);
			scoreFont = Content.Load<SpriteFont>("Towers/scoreFont");
			radiusTexture = Content.Load<Texture2D>("Level/radius");

			moneyTexture = Content.Load<Texture2D>("gold");
			healthTexture = Content.Load<Texture2D>("health");

			deathSound = Content.Load<SoundEffect>("Sounds/death");

			map = new Map(mapRect);
			map.Clicked += new Map.ClickedEventHandler(map_Clicked);
			map.LoadContent(Content);


			//Enemy flourEnemy = new Enemy(new Vector2(0, Engine.GameViewport.Height / 2), Content.Load<Texture2D>("Enemies/flour"), map.placedTowers);
			//flourEnemy.weakness = BULLET_TYPE.WATER;
			//AnimationFrame af = new AnimationFrame(4, 39, 64, 0, 0);
			//af.FramesPerSecond = 8;
			//flourEnemy.Animations.Add("pirateWalk", af);
			//flourEnemy.CurrentAnimationName = "pirateWalk";

			//levelEnemies.Add(flourEnemy);
			//levelEnemies.Add(new Enemy(new Vector2(0, Engine.GameViewport.Height / 2 - 60), Content.Load<Texture2D>("Enemies/currant"), map.placedTowers));
			//levelEnemies.Add(new Enemy(new Vector2(0, Engine.GameViewport.Height / 2 - 120), Content.Load<Texture2D>("Enemies/currant"), map.placedTowers));

			foreach (string s in Engine.assetNames("Content/Turret/Letters/"))
			{
				turretAmmoTextures.Add(Content.Load<Texture2D>("Turret/Letters/" + s));
			}
			turretTexture = Content.Load<Texture2D>("Turret/turret");
			InitLevel();
			turret = new ControlledTurret(new Vector2(1200, 900), turretTexture, turretAmmoTextures, levelEnemies);

			Song song = Content.Load<Song>("Sounds/background");
			MediaPlayer.IsRepeating = true;
			MediaPlayer.Play(song);
		}

		void map_Clicked(object sender, KinectClickArgs a)
		{
			if (placing && canPlace)
			{
				if (Engine.gamePlayer.BuyTower(towerToPlace.Cost))
				{
					towerToPlace.Position = new Vector2(a.position.X, a.position.Y) - towerToPlace.Size / 2;

					map.placedTowers.Add(towerToPlace);

					placing = false;
				}

				// towerToPlace = null;
			}

			if (placingUpgrade)
			{
				if (Engine.gamePlayer.BuyTower(upgradeCost))
				{


					foreach (Tower t in map.placedTowers)
					{
						if (t.drawRect.Contains(a.position.X, a.position.Y))
						{
							t.Upgrade(typeUpgrade);
							placingUpgrade = false;
							break;
						}
					}
				}
			}
		}


		public void Draw(SpriteBatch spriteBatch)
		{
			map.Draw(spriteBatch);


			foreach (Enemy e in levelEnemies)
				e.Draw(spriteBatch);

			turret.Draw(spriteBatch);

			if (placing)
			{
				spriteBatch.Draw(radiusTexture, new Rectangle((int)(Kinect.CursorPosition.X - towerToPlace.Radius), (int)(Kinect.CursorPosition.Y - towerToPlace.Radius), (int)(towerToPlace.Radius * 2), (int)(towerToPlace.Radius * 2)), radiusColour);
				towerToPlace.Draw(spriteBatch);
			}
			if (placingUpgrade)
				spriteBatch.Draw(placeUpgradeTexture, new Vector2(Kinect.CursorPosition.X - placeUpgradeTexture.Width, Kinect.CursorPosition.Y - placeUpgradeTexture.Height), Color.White);
			spriteBatch.Draw(ribbon, toolRect, Color.White);
			spriteBatch.DrawString(dialogTextFont, dialog, dialogPos, Color.White);

			if (STATE == levelStates.PLAYING)
			{
				foreach (Button t in uiUpgradeButtons)
				{
					t.Draw(spriteBatch);
				}
			}
			else
			{
				foreach (Button t in uiPlaceButtons)
				{
					t.Draw(spriteBatch);
				}
			}


			spriteBatch.Draw(ribbon, scoreRect, Color.White);
			spriteBatch.DrawString(scoreFont, "Money: " + Engine.gamePlayer.Money, new Vector2(scoreRect.X + 900, scoreRect.Y + 10), Color.White);
			spriteBatch.DrawString(scoreFont, "Wave: " + Level.wave, new Vector2(scoreRect.X + 1150, scoreRect.Y + 10), Color.White);
			spriteBatch.Draw(moneyTexture, new Vector2(scoreRect.X + 815, scoreRect.Y - 10), Color.White);

			int health = (int)Engine.gamePlayer.Health / 10;
			Vector2 healthPos = new Vector2(40, 0);
			for (int i = 0; i < health; ++i)
			{
				spriteBatch.Draw(healthTexture, new Rectangle((int)(i * healthPos.X), scoreRect.Y + 10, 30, 30), Color.White);

			}

			closeButton.Draw(spriteBatch);
		}

		private void InitLevel()
		{
			map.placedTowers.Clear();
			int mobsCreate = Level.wave * 10;
			Vector2 position = new Vector2(-80, 0);
			BULLET_TYPE weakness = BULLET_TYPE.NONE;
			for (int i = 0; i < mobsCreate; ++i)
			{
				Vector2 placePosition = new Vector2(position.X * i, Engine.GameViewport.Height / 2);
				Texture2D enemyTexture;
				AnimationFrame anim;
				switch (r.Next(2))
				{
					case 0:
						enemyTexture = enemyTextures["flour"];
						anim = new AnimationFrame(4, 39, 64, 0, 0);
						anim.FramesPerSecond = 8;
						weakness = BULLET_TYPE.WATER;
						break;
					case 1:
					default:
						enemyTexture = enemyTextures["fruit"];
						anim = new AnimationFrame(4, 52, 38, 0, 0);
						anim.FramesPerSecond = 8;
						weakness = BULLET_TYPE.POISON;
						break;
				}
				Enemy e = new Enemy(placePosition, enemyTexture, map.placedTowers);
                e.weakness = weakness;
				if (Level.wave > 0)
					e.Health *= 1.8f;
				e.Animations.Add("walk", anim);
				e.CurrentAnimationName = "walk";
				levelEnemies.Add(e);
			}
		}
		public void Update(GameTime gameTime)
		{
			closeButton.Update(gameTime);
			dialogPos = new Vector2((Engine.GameViewport.Width / 2) - Engine.StringLength(dialog, dialogTextFont).X, dialogPos.Y - 5);
			if (levelEnemies.Count == 0 && Engine.gamePlayer.Health > 0)
			{
				placingUpgrade = false;
				STATE = levelStates.PLACE_MODE;
				Level.wave++;
				Engine.gamePlayer.Health = 100f;
				InitLevel();
				//map.placedTowers.Clear();
				Engine.gamePlayer.Pay(500);
				int prevWave = Level.wave - 1;
				dialog = "Wave " + prevWave + " Completed!";
				dialogPos = new Vector2(0, Engine.GameViewport.Height + 100);

			}
			if (Engine.gamePlayer.Health < 10)
			{
				dialog = "Wave Failed! Have another go!";
				dialogPos = new Vector2(0, Engine.GameViewport.Height + 100);
				STATE = levelStates.PLACE_MODE;
				Engine.gamePlayer.Health = 100f;
				if(Engine.gamePlayer.Money < 500)
					Engine.gamePlayer.Pay(500);
				levelEnemies.Clear();
				InitLevel();
			}

			if (STATE == levelStates.PLAYING)
			{
				turret.Update(gameTime);
				foreach (Enemy e in levelEnemies)
					e.Update(gameTime);
				foreach (Button t in uiUpgradeButtons)
					t.Update(gameTime);
				for (int i = 0; i < levelEnemies.Count; ++i)
				{
					Enemy e = levelEnemies[i];
					if (e.Health <= 0)
					{
						deathSound.Play(0.2f, 0, 0);
						levelEnemies.Remove(e);
						Engine.gamePlayer.Pay(e.Bounty);
					}
					if (e.Position.X > Engine.GameViewport.Width)
					{
						Engine.gamePlayer.Health -= 10;
						levelEnemies.Remove(e);
					}
				}
			}
			else
			{
				foreach (Button t in uiPlaceButtons)
					t.Update(gameTime);
			}
			map.Update(gameTime);



			if (placing)
				towerToPlace.Position = new Vector2(Kinect.CursorPosition.X, Kinect.CursorPosition.Y) - towerToPlace.Size / 2;



			if (placing)
			{
				foreach (Tower t in map.placedTowers)
				{
					// t.Active = true;
					if (Engine.CheckCollision(t.Origin, towerToPlace.Origin, t.Radius, towerToPlace.Radius) || !Engine.gamePlayer.AffordTower(towerToPlace.Cost))
					{
						radiusColour = Color.Red;
						canPlace = false;
						break;
					}
					else
					{
						radiusColour = Color.White;
						canPlace = true;
					}
				}

			}

		}

	}
}
